#include "InternalMaterial.h"
#include "Shader.h"
#include "glm/glm.hpp"
#include <memory>
#include <vector>
using namespace Umikaze::Core;

std::unique_ptr<Shader> MotionVectorMaterial::_shader = nullptr;

void MotionVectorMaterial::bind(const glm::mat4 &modelMatrix,
                                const glm::mat4 &oldModelMatrix,
                                const glm::mat4 &oldViewMatrix,
                                const glm::mat4 &oldProjMatrix,
                                const std::shared_ptr<Buffer> &cameraBuffer) {
  if (!_shader) {
    _shader =
        std::make_unique<Shader>("MotionVector.vert", "MotionVector.frag");
  }
  _shader->setMat4("modelMatrix", modelMatrix);
  _shader->setMat4("oldModelMatrix", oldModelMatrix);
  _shader->setMat4("oldViewMatrix", oldViewMatrix);
  _shader->setMat4("oldProjMatrix", oldProjMatrix);
  _shader->setBuffer("cameraData", cameraBuffer);
  _shader->bind();
}

std::unique_ptr<Shader> DrawDepthMaterial::_shader = nullptr;

void DrawDepthMaterial::bind(const glm::mat4 &modelMatrix,
                             const std::shared_ptr<Buffer> &cameraBuffer) {
  if (!_shader) {
    _shader = std::make_unique<Shader>("DrawDepth.vert", "DrawDepth.frag");
  }
  _shader->setBuffer("cameraData", cameraBuffer);
  _shader->setMat4("modelMatrix", modelMatrix);
  _shader->bind();
}

std::unique_ptr<Shader> DrawShadowMaterial::_shader = nullptr;

void DrawShadowMaterial::bind(const glm::mat4 &modelMatrix,
                              const glm::mat4 &lightSpaceMatrix) {
  if (!_shader) {
    _shader = std::make_unique<Shader>("DrawShadow.vert", "DrawShadow.frag");
  }

  _shader->setMat4("modelMatrix", modelMatrix);
  _shader->setMat4("lightSpaceMatrix", lightSpaceMatrix);
  _shader->bind();
}

std::unique_ptr<Shader> DrawShadowCascadeMaterial::_shader = nullptr;
void DrawShadowCascadeMaterial::bind(
    const glm::mat4 &modelMatrix,
    const std::shared_ptr<Buffer> &lightSpaceMatrices, uint32_t matrixCount) {
  if (!_shader) {
    _shader = std::make_unique<Shader>("DrawShadowCascade.vert",
                                       "DrawShadowCascade.frag",
                                       "DrawShadowCascade.geom");
  }
  _shader->setMat4("modelMatrix", modelMatrix);
  _shader->setInt("level", matrixCount);
  _shader->setBuffer("lightSpaceMatricesData", lightSpaceMatrices);
  _shader->bind();
}
